package helper

import (
	"reflect"
	"strconv"
)

func SetDefaults(s interface{}) {
	v := reflect.ValueOf(s).Elem()
	t := v.Type()

	for i := 0; i < v.NumField(); i++ {
		field := v.Field(i)
		tag := t.Field(i).Tag.Get("default")

		if field.Kind() != reflect.Struct && (tag == "" || !field.CanSet()) {
			continue
		}

		switch field.Kind() {
		case reflect.String:
			if field.String() == "" {
				field.SetString(tag)
			}
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			if field.Int() == 0 {
				if intValue, err := strconv.ParseInt(tag, 10, 64); err == nil {
					field.SetInt(intValue)
				}
			}
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
			if field.Uint() == 0 {
				if uintValue, err := strconv.ParseUint(tag, 10, 64); err == nil {
					field.SetUint(uintValue)
				}
			}
		case reflect.Float32, reflect.Float64:
			if field.Float() == 0 {
				if floatValue, err := strconv.ParseFloat(tag, 64); err == nil {
					field.SetFloat(floatValue)
				}
			}
		case reflect.Bool:
			if !field.Bool() {
				if boolValue, err := strconv.ParseBool(tag); err == nil {
					field.SetBool(boolValue)
				}
			}
		case reflect.Struct:
			fieldPtr := field.Addr().Interface()
			SetDefaults(fieldPtr)
		}
	}
}
